home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-02-19 | 12.0 KB | 388 lines | [TEXT/CWIE] |
-
- #include "AbstractCollector.h"
- #include "MarkToken.h"
-
- //
- // We will sometimes be asked to retrieve "any" item,
- // in which case we will need to generate random numbers.
- //
- #include "PseudoRandom.h"
-
- #include <AppleEvents.h>
- #include <AERegistry.h>
- #include <ASRegistry.h>
-
- //========================================================================================
- // Classs TCollectorBehavior
- //========================================================================================
-
- ImplementSmallClassData(TCollectorBehavior, clCollectorBehavior);
-
- //----------------------------------------------------------------------------------------
- // TCollectorBehavior::CollectorBehaviorOwner
- //----------------------------------------------------------------------------------------
- TAbstractCollector* TCollectorBehavior::CollectorBehaviorOwner() const
- {
- return (TAbstractCollector*)this->BehaviorOwner();
- } // TCollectorBehavior::CollectorBehaviorOwner
-
- //----------------------------------------------------------------------------------------
- // TCollectorBehavior::CollectorRequestDynamicBehavior
- //----------------------------------------------------------------------------------------
- long TCollectorBehavior::CollectorRequestDynamicBehavior(const TAETransaction& t, long requestID, void* param)
- {
- TCollectorBehavior* nextBehavior = this->NextCollectorBehavior();
-
- if(nextBehavior != nil)
- return nextBehavior->CollectorRequestDynamicBehavior(t, requestID, param);
- else
- return this->CollectorBehaviorOwner()->CollectorRequestDefaultBehavior(t, requestID, param);
- }
-
- //========================================================================================
- // Classs TAbstractCollector
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // TAbstractCollector::CollectorRequest
- //----------------------------------------------------------------------------------------
- long TAbstractCollector::CollectorRequest(const TAETransaction& t, long requestID, void* param /* = nil*/)
- {
- TCollectorBehavior* behavior = FirstCollectorBehavior();
-
- if(behavior != nil)
- return behavior->CollectorRequestDynamicBehavior(t, requestID, param);
- else
- return this->CollectorRequestDefaultBehavior(t, requestID, param);
- }
-
- //----------------------------------------------------------------------------------------
- // TAbstractCollector::CollectorRequestDefaultBehavior
- //----------------------------------------------------------------------------------------
- long TAbstractCollector::CollectorRequestDefaultBehavior(const TAETransaction&, long requestID, void* /*param = nil*/)
- {
- long result = 0;
-
- switch(requestID)
- {
- case kWaitForAsyncSearchesToComplete:
- case kAsyncSearchesComplete:
- result = true;
- break;
-
- case kSearchShouldIterateBackwards:
- case kCollectionIsFull:
- result = false;
- break;
-
- default:
- result = kUnknownCollectorRequest;
- }
-
- return result;
- } // TAbstractCollector::CollectorRequestDefaultBehavior
-
- //----------------------------------------------------------------------------------------
- // TAbstractCollector::~TAbstractCollector
- //----------------------------------------------------------------------------------------
- TAbstractCollector::~TAbstractCollector()
- {
- } // TAbstractCollector::~TAbstractCollector
-
- //----------------------------------------------------------------------------------------
- // TAbstractCollector::FirstBehavior
- //----------------------------------------------------------------------------------------
- TBehavior* TAbstractCollector::FirstBehavior() const
- {
- return fFirstBehavior;
- }
-
- //----------------------------------------------------------------------------------------
- // TAbstractCollector::SetFirstBehavior
- //----------------------------------------------------------------------------------------
- void TAbstractCollector::SetFirstBehavior(TBehavior* firstBehavior)
- {
- fFirstBehavior = firstBehavior;
- }
-
- enum
- {
- kTakeFirstItemOnly = 'one!' // Used internally by TObjectCollector
- };
-
- //========================================================================================
- // Classs TObjectCollector
- //========================================================================================
-
- TObjectCollector::TObjectCollector(TDescriptor scopeOfSearch) :
- fCollection(nil),
- fScopeOfSearch(scopeOfSearch),
- fCollectionFull(false),
- fIterateBackwards(false),
- fStartOfRange(1),
- fEndOfRange(0x7FFFFFFF),
- fPostProcessListStart(0),
- fPostProcessListStop(0),
- fNumberOfItemsAdded(0)
- {
- TDescriptor scopeOfSearchRecord;
-
- //
- // First, process the single-descriptor entries.
- // "every" item may be specified; any other possible
- // value (any, middle, etc.) specifies but a single
- // object.
- //
- if((scopeOfSearch.DescriptorType() == typeLongInteger) || (scopeOfSearch.DescriptorType() == typeAbsoluteOrdinal))
- {
- InterpretWhoseRangeEntry(scopeOfSearch, fStartOfRange, fEndOfRange, fPostProcessListStart);
- //
- // If the special processing mode is "any" or "middle" or
- // something like that, then we only want to take a single
- // item.
- //
- if(fPostProcessListStart != 0)
- fPostProcessListStop = kTakeFirstItemOnly;
- }
- //
- // Next, process range descriptors. These are usually in the
- // form "item X through item Y", but they may be much stranger
- // than that ("middle item through any item", for example).
- //
- // n.b. The object support library always converts the formRange
- // descriptor into a typeWhoseRange descriptor to make life easier
- // for its clients. We don't bother to do this conversion because
- // we might as well just recognize formRange here, and not bother
- // parsing it earlier.
- //
- // The following 'typeWhoseRange' code is only executed if
- // AEResolve is used.
- //
- else if(scopeOfSearch.DescriptorType() == typeWhoseRange)
- {
- scopeOfSearchRecord = scopeOfSearch.Coerce(typeAERecord);
-
- TDescriptor temp;
- long rangeTemp = 0;
-
- //
- // Get the start and the end of the range
- //
- temp = scopeOfSearchRecord.GetDescriptorParameter(keyAEWhoseRangeStart);
- InterpretWhoseRangeEntry(temp, fStartOfRange, rangeTemp, fPostProcessListStart);
- temp.Dispose();
- temp = scopeOfSearchRecord.GetDescriptorParameter(keyAEWhoseRangeStop);
- InterpretWhoseRangeEntry(temp, rangeTemp, fEndOfRange, fPostProcessListStop);
- temp.Dispose();
-
- //
- // If the end of the range is the last item, that's nothing special.
- //
- if(fEndOfRange == -1)
- {
- fPostProcessListStop = 0;
- fEndOfRange = 0x7FFFFFFF;
- }
- }
- //
- // The following 'formRange' code is only used if AEResolve is NOT used.
- //
- else if(scopeOfSearch.DescriptorType() == formRange)
- {
- scopeOfSearchRecord = scopeOfSearch.Coerce(typeAERecord);
-
- TDescriptor temp;
- TDescriptor temp2;
- DescType unusedDesiredClass;
- DescType unusedKeyForm;
- long rangeTemp = 0;
-
- //
- // Get the start and the end of the range
- //
- temp2 = scopeOfSearchRecord.GetDescriptorParameter(keyAERangeStart);
- temp2.GetObjectSpecifierParameters(unusedDesiredClass, unusedKeyForm, &temp);
- InterpretWhoseRangeEntry(temp, fStartOfRange, rangeTemp, fPostProcessListStart);
- temp.Dispose();
- temp2.Dispose();
- temp2 = scopeOfSearchRecord.GetDescriptorParameter(keyAERangeStop);
- temp2.GetObjectSpecifierParameters(unusedDesiredClass, unusedKeyForm, &temp);
- InterpretWhoseRangeEntry(temp, rangeTemp, fEndOfRange, fPostProcessListStop);
- temp.Dispose();
- temp2.Dispose();
-
- //
- // If the end of the range is the last item, that's nothing special.
- //
- if(fEndOfRange == -1)
- {
- fPostProcessListStop = 0;
- fEndOfRange = 0x7FFFFFFF;
- }
- }
-
- scopeOfSearchRecord.Dispose();
- }
-
- //----------------------------------------------------------------------------------------
- // TObjectCollector::CollectorRequestDefaultBehavior
- //----------------------------------------------------------------------------------------
- long TObjectCollector::CollectorRequestDefaultBehavior(const TAETransaction& t, long requestID, void* param /* = nil*/)
- {
- long result = 0;
-
- switch(requestID)
- {
- case kSearchShouldIterateBackwards:
- result = fIterateBackwards;
- break;
-
- case kCollectionIsFull:
- result = fCollectionFull;
- break;
-
- default:
- result = TAbstractCollector::CollectorRequestDefaultBehavior(t, requestID, param);
- }
-
- return result;
- } // TObjectCollector::CollectorRequestDefaultBehavior
-
- //----------------------------------------------------------------------------------------
- // TObjectCollector::AddToCollection
- //----------------------------------------------------------------------------------------
- void TObjectCollector::AddToCollection(TAbstractScriptableObject* itemToAdd)
- {
- ++fNumberOfItemsAdded;
- Boolean shouldAddToCollection = (fNumberOfItemsAdded >= fStartOfRange) && ((fNumberOfItemsAdded <= fEndOfRange) || (fEndOfRange < 0));
-
- if((shouldAddToCollection == true) && (fCollectionFull == false))
- {
- if(fCollection == nil)
- {
- fCollection = new TMarkToken(kAlwaysMakeCollection);
- fCollection->IMarkToken();
- }
-
- //
- // â—ŠScript: Should the mark type be a field of TObjectCollector?
- //
- fCollection->AdoptToken(itemToAdd, kAlwaysMakeCollection);
- if((fNumberOfItemsAdded >= fEndOfRange) && (fEndOfRange > 0))
- fCollectionFull = true;
- }
- }
-
- //----------------------------------------------------------------------------------------
- // TObjectCollector::CollectionResult
- //----------------------------------------------------------------------------------------
- TAbstractScriptableObject* TObjectCollector::CollectionResult()
- {
- //
- // Before we return the collection, we must postprocess it to
- // see if some items need to be pruned out (for example, if we're
- // to return the middle item, then we want to prune out all but one
- // item from the result list)
- //
- long firstItemToTake = fStartOfRange;
- long lastItemToTake = fEndOfRange;
- long middleItem = (fNumberOfItemsAdded + 1) >> 1;
-
- //
- // Skip preprocessing if there were no items in the result
- //
- if(fNumberOfItemsAdded > 0)
- {
- switch(fPostProcessListStart)
- {
- case kAEMiddle:
- firstItemToTake = middleItem;
- break;
-
- case kAEAny:
- firstItemToTake = PseudoRandomFromMToN(1, fNumberOfItemsAdded);
- break;
-
- }
-
- switch(fPostProcessListStop)
- {
- case kAEMiddle:
- lastItemToTake = middleItem;
- break;
-
- case kAEAny:
- lastItemToTake = PseudoRandomFromMToN(1, fNumberOfItemsAdded);
- break;
-
- case kTakeFirstItemOnly:
- lastItemToTake = firstItemToTake;
- break;
- }
-
- //
- // If we already threw out some items, then adjust the
- // range accordingly.
- //
- if(fStartOfRange > 1)
- {
- lastItemToTake -= (fStartOfRange - 1);
- firstItemToTake -= (fStartOfRange - 1);
- }
-
- //
- // Just like the OSL, we call our adjust marks
- // proc to prune down the list once we've determined
- // which items to take.
- //
- if(fCollection)
- fCollection->AdjustMarks(firstItemToTake, lastItemToTake);
- }
-
- return fCollection;
- }
-
- //----------------------------------------------------------------------------------------
- // TObjectCollector::InterpretWhoseRangeEntry
- //
- // This routine does common pre-processing of a whose range entry; the
- // TObjectCollector uses the results from this routine to determine what
- // the appropriate range of items should actually be.
- //----------------------------------------------------------------------------------------
- void TObjectCollector::InterpretWhoseRangeEntry(TDescriptor rangeEntry, long& start, long& end, unsigned long& special)
- {
- if(rangeEntry.DescriptorType() == typeLongInteger)
- {
- start = rangeEntry.GetSInt32Data();
- end = start;
- }
- else if(rangeEntry.DescriptorType() == typeAbsoluteOrdinal)
- {
- DescType rangeEntryOrdinal = rangeEntry.GetDescTypeData(typeAbsoluteOrdinal);
- switch(rangeEntryOrdinal)
- {
- case kAEFirst:
- start = 1;
- end = 1;
- break;
-
- case kAELast:
- start = -1;
- end = -1;
- break;
-
- case kAEMiddle:
- case kAEAny:
- start = 1;
- end = 0x7FFFFFFF;
- special = rangeEntryOrdinal;
- break;
-
- case kAEAll:
- start = 1;
- end = 0x7FFFFFFF;
- break;
- }
- }
- } // TObjectCollector::InterpretWhoseRangeEntry
-